home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swags_z.zip / SOUND.SWG / 0033_SOUND Machine.pas < prev    next >
Pascal/Delphi Source File  |  1993-10-28  |  10KB  |  319 lines

  1. {===========================================================================
  2. Date: 08-31-93 (22:24)
  3. From: WIM VAN.VOLLENHOVEN
  4. Subj: Sound Module
  5. ---------------------------------------------------------------------------
  6. Well.. here is the source code i've found in a pascal toolbox (ECO)
  7. which emulates the play function of qbasic :-)
  8.  
  9. {
  10.   call: play(string)
  11.  
  12.         music_string --- the string containing the encoded music to be
  13.                          played.  the format is the same as that of the
  14.                          microsoft basic play statement.  the string
  15.                          must be <= 254 characters in length.
  16.  
  17.   calls:  sound
  18.           getint  (internal)
  19.  
  20.   remarks:  the characters accepted by this routine are:
  21.  
  22.             a - g       musical notes
  23.             # or +      following a - g note, indicates sharp
  24.             -           following a - g note, indicates flat
  25.             <           move down one octave
  26.             >           move up one octave
  27.             .           dot previous note (extend note duration by 3/2)
  28.             mn          normal duration (7/8 of interval between notes)
  29.             ms          staccato duration
  30.             ml          legato duration
  31.             ln          length of note (n=1-64; 1=whole note,4=quarter note)
  32.             pn          pause length (same n values as ln above)
  33.             tn          tempo,n=notes/minute (n=32-255,default n=120)
  34.             on          octave number (n=0-6,default n=4)
  35.             nn          play note number n (n=0-84)
  36.  
  37.             the following two commands are ignored by play:
  38.  
  39.             mf          complete note before continuing
  40.             mb          another process may begin before speaker is
  41.                         finished playing note
  42.  
  43.   important --- setdefaultnotes must have been called at least once before
  44.                 this routine is called.
  45. }
  46.  
  47. unit u_play;
  48. interface
  49.  
  50. uses
  51.   crt
  52.  
  53.   ;
  54.  
  55. const
  56.   note_octave   : integer = 4;     { current octave for note            }
  57.   note_fraction : real    = 0.875; { fraction of duration given to note }
  58.   note_duration : integer = 0;     { duration of note     ^^semi-legato }
  59.   note_length   : real    = 0.25;  { length of note }
  60.   note_quarter  : real    = 500.0; { moderato pace (principal beat)     }
  61.  
  62.  
  63.  
  64.   procedure quitsound;
  65.   procedure startsound;
  66.   procedure errorbeep;
  67.   procedure warningbeep;
  68.   procedure smallbeep;
  69.   procedure setdefaultnotes;
  70.   procedure play(s: string);
  71.   procedure beep(h, l: word);
  72.  
  73.  
  74.  
  75. implementation
  76.  
  77.  
  78.  
  79.  
  80.   procedure quitsound;
  81.   var i: word;
  82.   begin
  83.     for i := 100 downto 1 do begin sound(i*10); delay(2) end;
  84.     for i := 1 to 800 do begin sound(i*10); delay(2) end;
  85.     nosound;
  86.   end;
  87.  
  88.   procedure startsound;
  89.   var i: word;
  90.   begin
  91.     for i := 100 downto 1 do begin sound(i*15); delay(2) end;
  92.     for i := 1 to 100 do begin sound(i*15); delay(2) end; nosound;
  93.     delay(100); for i := 100 downto 1 do begin sound(i*10); delay(2) end;
  94.     nosound;
  95.   end;
  96.  
  97.  
  98.   procedure errorbeep;
  99.   begin
  100.     sound(2000); delay(75); sound(1000); delay(75); nosound;
  101.   end;
  102.  
  103.  
  104.   procedure warningbeep;
  105.   begin
  106.     sound(500); delay(500); nosound;
  107.   end;
  108.  
  109.   procedure smallbeep;
  110.   begin
  111.     sound(300); delay(50); nosound;
  112.   end;
  113.  
  114.  
  115.  
  116.  
  117.  
  118. procedure setdefaultnotes;
  119. begin
  120.    note_octave   := 4;             { default octave                      }
  121.    note_fraction := 0.875;         { default sustain is semi-legato      }
  122.    note_length   := 0.25;          { note is quarter note by default     }
  123.    note_quarter  := 500.0;         { moderato pace by default            }
  124. end;
  125.  
  126.  
  127.  
  128. procedure play(s: string);
  129. const
  130.                                       { offsets in octave of natural notes }
  131.  note_offset   : array[ 'A'..'G' ] of integer = (9,11,0,2,4,5,7);
  132.  
  133.                                       { frequencies for 7 octaves          }
  134.    note_freqs: array[ 0 .. 84 ] of integer =
  135. {
  136.       c    c#     d    d#     e     f    f#     g    g#     a    a#     b
  137. }
  138. (    0,
  139.      65,  69,  73,  78,  82,  87,  92,  98, 104, 110, 116, 123,
  140.     131, 139, 147, 156, 165, 175, 185, 196, 208, 220, 233, 247,
  141.     262, 278, 294, 312, 330, 350, 370, 392, 416, 440, 466, 494,
  142.     524, 556, 588, 624, 660, 700, 740, 784, 832, 880, 932, 988,
  143.    1048,1112,1176,1248,1320,1400,1480,1568,1664,1760,1864,1976,
  144.    2096,2224,2352,2496,2640,2800,2960,3136,3328,3520,3728,3952,
  145.    4192,4448,4704,4992,5280,5600,5920,6272,6656,7040,7456,7904 );
  146.  
  147.    quarter_note = 0.25;            { length of a quarter note }
  148.  
  149.    digits : set of '0'..'9' = ['0'..'9'];
  150.  
  151. var
  152.  
  153.    play_freq     : integer;        { frequency of note to be played }
  154.    play_duration : integer;        { duration to sound note }
  155.    rest_duration : integer;        { duration of rest after a note }
  156.    i             : integer;        { offset in music string }
  157.    c             : char;           { current character in music string }
  158.                                    { note frequencies }
  159.    freq          : array[0..6,0..11] of integer absolute note_freqs;
  160.    n             : integer;
  161.    xn            : real;
  162.    k             : integer;
  163.  
  164.   function getint : integer;
  165.   var n: integer;
  166.  
  167.   begin { getint }
  168.     n := 0;
  169.     while(s[i] in digits) do begin n := n*10+ord(s[i])-ord('0'); inc(i) end;
  170.     dec(i); getint := n;
  171.   end   { getint };
  172.  
  173. begin
  174.   s := s + ' ';                   { append blank to end of music string }
  175.   i := 1;                           { point to first character in music }
  176.   while(i < length(s)) do begin      { begin loop over music string }
  177.     c := upcase(s[i]);        { get next character in music string }
  178.     case c of                 { interpret it                       }
  179.        'A'..'G' : begin { a note }
  180.           n         := note_offset[ c ];
  181.           play_freq := freq[ note_octave ,n ];
  182.           xn := note_quarter * (note_length / quarter_note);
  183.           play_duration := trunc(xn * note_fraction);
  184.           rest_duration := trunc(xn * (1.0 - note_fraction));
  185.                                       { check for sharp/flat }
  186.           if s[i+1] in ['#','+','-' ] then
  187.              begin
  188.                 inc(i);
  189.                 case s[i] of
  190.                    '#',
  191.                    '+' : play_freq :=
  192.                             freq[ note_octave ,succ(n) ];
  193.                    '-' : play_freq :=
  194.                             freq[ note_octave ,pred(n) ];
  195.                    else  ;
  196.                 end { case };
  197.  
  198.              end;
  199.  
  200.                    { check for note length }
  201.  
  202.           if (s[i+1] in digits) then
  203.              begin
  204.  
  205.                 inc(i);
  206.                 n  := getint;
  207.                 xn := (1.0 / n) / quarter_note;
  208.  
  209.                 play_duration :=
  210.                     trunc(note_fraction * note_quarter * xn);
  211.  
  212.                 rest_duration :=
  213.                    trunc((1.0 - note_fraction) *
  214.                           xn * note_quarter);
  215.  
  216.              end;
  217.                    { check for dotting }
  218.  
  219.              if s[i+1] = '.' then
  220.                 begin
  221.  
  222.                    xn := 1.0;
  223.  
  224.                    while(s[i+1] = '.') do
  225.                       begin
  226.                          xn := xn * 1.5;
  227.                          inc(i);
  228.                       end;
  229.  
  230.                    play_duration :=
  231.                        trunc(play_duration * xn);
  232.  
  233.                 end;
  234.  
  235.                        { play the note }
  236.  
  237.           sound(play_freq);
  238.           delay(play_duration);
  239.           nosound;
  240.           delay(rest_duration);
  241.         end   { a note };
  242.  
  243.        'M' : begin { 'M' commands }
  244.          inc(i);
  245.          c := s[i];
  246.          case c of
  247.            'F' : ;
  248.            'B' : ;
  249.            'N' : note_fraction := 0.875;
  250.            'L' : note_fraction := 1.000;
  251.            'S' : note_fraction := 0.750;
  252.            else ;
  253.          end { case };
  254.        end   { 'M' commands };
  255.  
  256.        'O' : begin { set octave }
  257.          inc(i);
  258.          n := ord(s[i]) - ord('0');
  259.          if (n < 0) or (n > 6) then n := 4;
  260.          note_octave := n;
  261.        end   { set octave };
  262.  
  263.        '<' : begin { drop an octave }
  264.          if note_octave > 0 then dec(note_octave);
  265.        end   { drop an octave };
  266.  
  267.        '>' : begin { ascend an octave }
  268.          if note_octave < 6 then inc(note_octave);
  269.        end   { ascend an octave };
  270.  
  271.        'N' : begin { play note n }
  272.          inc(i); n := getint;
  273.          if (n > 0) and (n <= 84) then begin
  274.            play_freq     := note_freqs[ n ];
  275.            xn            := note_quarter * (note_length / quarter_note);
  276.            play_duration := trunc(xn * note_fraction);
  277.            rest_duration := trunc(xn * (1.0 - note_fraction));
  278.          end else if (n = 0) then begin
  279.            play_freq     := 0; play_duration := 0;
  280.            rest_duration := trunc(note_fraction * note_quarter *
  281.                                  (note_length / quarter_note));
  282.          end;
  283.          sound(play_freq); delay(play_duration); nosound;
  284.          delay(rest_duration);
  285.        end   { play note n };
  286.        'L' : begin { set length of notes }
  287.          inc(i); n := getint;
  288.          if n > 0 then note_length := 1.0 / n;
  289.        end   { set length of notes };
  290.  
  291.        'T' : begin { # of quarter notes in a minute }
  292.          inc(i); n := getint;
  293.          note_quarter := (1092.0 / 18.2 / n) * 1000.0;
  294.        end   { # of quarter notes in a minute };
  295.  
  296.        'P' : begin { pause }
  297.          inc(i); n := getint;
  298.          if (n <  1) then n := 1 else if (n > 64) then n := 64;
  299.          play_freq := 0; play_duration := 0;
  300.          rest_duration := trunc(((1.0 / n) / quarter_note) * note_quarter);
  301.          sound(play_freq); delay(play_duration); nosound;
  302.          delay(rest_duration);
  303.        end   { pause };
  304.  
  305.        else  { ignore other stuff };
  306.     end { case };
  307.     inc(i);
  308.   end  { interpret music };
  309.   nosound;                         { make sure sound turned off when through }
  310. end;
  311.  
  312.  
  313. procedure beep(h, l: word);
  314. begin
  315.   sound(h); delay(l); nosound;
  316. end;
  317.  
  318. end. { of unit }
  319.